/**
 * 骰子概率计算工具函数
 */

/**
 * 计算n个骰子所有可能的点数和的理论概率分布
 * @param {Number} diceCount - 骰子数量
 * @returns {Object} 包含每个点数和的理论概率
 */
export function calculateTheoreticalProbability(diceCount) {
  // 一个骰子有6个面，点数为1-6
  const SIDES = 6;
  
  // 计算所有可能的组合总数
  const totalCombinations = Math.pow(SIDES, diceCount);
  
  // 可能的点数和范围：从diceCount（每个骰子都是1）到diceCount*6（每个骰子都是6）
  const minSum = diceCount;
  const maxSum = diceCount * SIDES;
  
  // 存储每个可能的点数和出现的次数
  const combinationCounts = {};
  
  // 递归函数：计算所有可能的骰子组合
  function calculateCombinations(currentDice, remainingDice, currentSum) {
    // 递归基础：当没有剩余骰子需要计算时，记录当前和
    if (remainingDice === 0) {
      combinationCounts[currentSum] = (combinationCounts[currentSum] || 0) + 1;
      return;
    }
    
    // 对当前骰子的每个可能点数进行递归
    for (let i = 1; i <= SIDES; i++) {
      calculateCombinations([...currentDice, i], remainingDice - 1, currentSum + i);
    }
  }
  
  // 开始递归计算
  calculateCombinations([], diceCount, 0);
  
  // 将组合数转换为概率
  const theoreticalProbabilities = {};
  for (let sum = minSum; sum <= maxSum; sum++) {
    theoreticalProbabilities[sum] = (combinationCounts[sum] || 0) / totalCombinations;
  }
  
  return theoreticalProbabilities;
}

/**
 * 使用蒙特卡洛方法模拟掷骰子，并计算各点数和的频率
 * @param {Number} diceCount - 骰子数量
 * @param {Number} simulationCount - 模拟次数
 * @returns {Object} 包含模拟结果的点数和频率
 */
export function simulateDiceRolls(diceCount, simulationCount) {
  // 一个骰子有6个面，点数为1-6
  const SIDES = 6;
  
  // 可能的点数和范围
  const minSum = diceCount;
  const maxSum = diceCount * SIDES;
  
  // 初始化计数器，记录每个点数和出现的次数
  const occurrences = {};
  for (let sum = minSum; sum <= maxSum; sum++) {
    occurrences[sum] = 0;
  }
  
  // 进行模拟
  for (let i = 0; i < simulationCount; i++) {
    let rollSum = 0;
    
    // 模拟diceCount个骰子的投掷
    for (let j = 0; j < diceCount; j++) {
      // 生成1-6的随机数
      const roll = Math.floor(Math.random() * SIDES) + 1;
      rollSum += roll;
    }
    
    // 记录本次投掷的点数和
    occurrences[rollSum]++;
  }
  
  // 将出现次数转换为频率
  const simulatedFrequencies = {};
  for (let sum = minSum; sum <= maxSum; sum++) {
    simulatedFrequencies[sum] = occurrences[sum] / simulationCount;
  }
  
  return simulatedFrequencies;
}

/**
 * 生成两种频率的对比数据，用于图表展示
 * @param {Object} theoretical - 理论概率
 * @param {Object} simulated - 模拟频率
 * @returns {Array} 表格数据
 */
export function generateComparisonData(theoretical, simulated) {
  // 存储对比结果的数组
  const comparisonData = [];
  
  // 遍历所有点数和
  for (const sum in theoretical) {
    if (Object.prototype.hasOwnProperty.call(theoretical, sum)) {
      comparisonData.push({
        sum: parseInt(sum),
        theoretical: theoretical[sum].toFixed(4),
        simulated: (simulated[sum] || 0).toFixed(4)
      });
    }
  }
  
  // 按点数和排序
  comparisonData.sort((a, b) => a.sum - b.sum);
  
  return comparisonData;
}

/**
 * 计算两个骰子所有可能点数和组合的详细信息
 * 用于教学展示每个点数和对应的具体骰子组合
 * @returns {Object} 每个点数和及其对应的骰子组合
 */
export function getTwoDiceCombinations() {
  const combinations = {};
  
  // 遍历第一个骰子的所有可能点数
  for (let dice1 = 1; dice1 <= 6; dice1++) {
    // 遍历第二个骰子的所有可能点数
    for (let dice2 = 1; dice2 <= 6; dice2++) {
      // 计算两个骰子的点数和
      const sum = dice1 + dice2;
      
      // 如果这个和还没有记录过，初始化为空数组
      if (!combinations[sum]) {
        combinations[sum] = [];
      }
      
      // 添加这个组合
      combinations[sum].push([dice1, dice2]);
    }
  }
  
  return combinations;
} 